package com.nowar.common.util;

import org.springframework.util.StringUtils;

import java.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

/**
 * 日期工具类
 *
 * @Author: 谢无殇。
 * @Date : 2023-01-16 22:08
 */
public class DateUtil {
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String UTC = "UTC";


    /**
     * +8区
     *
     * @return ZoneId
     */
    public static ZoneId zoneId() {
        return ZoneId.of("Asia/Shanghai");
    }

    /**
     * utc
     *
     * @param utc 时区
     * @return ZoneId
     */
    public static ZoneId zoneId(String utc) {
        if (StringUtils.isEmpty(utc)) {
            return ZoneId.of(UTC);
        }
        return ZoneId.of(utc);
    }

    /**
     * 中国时间
     *
     * @return LocalDateTime
     */
    public static LocalDateTime now() {
        return LocalDateTime.now(zoneId());
    }

    /**
     * UTC时间
     *
     * @return LocalDateTime
     */
    public static LocalDateTime nowUTC() {
        return LocalDateTime.now(zoneId(null));
    }

    /**
     * 时间转成字符串
     *
     * @param localDateTime LocalDateTime
     * @param pattern       格式
     * @return LocalDateTime
     */
    public static String formatToPattern(LocalDateTime localDateTime, String pattern) {
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 时间转成字符串
     *
     * @return LocalDateTime
     */
    public static String format() {
        return now().format(DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
    }

    /**
     * 字符串转成时间
     *
     * @param date    字符串 时间
     * @param pattern 格式
     * @return LocalDateTime
     */
    public static LocalDateTime formatToDateTime(String date, String pattern) {
        return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 获取时间戳
     *
     * @return 时间戳
     */
    public static long toEpochMilli() {
        return nowUTC().toInstant(ZoneOffset.UTC).toEpochMilli();
    }

    /**
     * 根据时间戳获取时间
     *
     * @param timestamp 时间戳
     * @param zoneId    时区
     * @return LocalDateTime
     */
    public static LocalDateTime epochMilliToLocalDateTime(long timestamp, ZoneId zoneId) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        return LocalDateTime.ofInstant(instant, zoneId);
    }

    /**
     * 年开始时间
     *
     * @param localDateTime LocalDateTime
     * @return LocalDateTime
     */
    public static LocalDateTime yearStart(LocalDateTime localDateTime) {
        return localDateTime.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 年结束时间
     *
     * @param localDateTime LocalDateTime
     * @return LocalDateTime
     */
    public static LocalDateTime yearEnd(LocalDateTime localDateTime) {
        return yearStart(localDateTime).plusYears(1).minusNanos(1);
    }

    /**
     * 月开始时间
     *
     * @param localDateTime LocalDateTime
     * @return LocalDateTime
     */
    public static LocalDateTime monthStart(LocalDateTime localDateTime) {
        return localDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 月结束时间
     *
     * @param localDateTime LocalDateTime
     * @return LocalDateTime
     */
    public static LocalDateTime monthEnd(LocalDateTime localDateTime) {
        return monthStart(localDateTime).plusMonths(1).minusNanos(1);
    }

    /**
     * 日开始时间
     *
     * @param localDateTime LocalDateTime
     * @return LocalDateTime
     */
    public static LocalDateTime dayStart(LocalDateTime localDateTime) {
        return localDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 日结束时间
     *
     * @param localDateTime LocalDateTime
     * @return LocalDateTime
     */
    public static LocalDateTime dayEnd(LocalDateTime localDateTime) {
        return dayStart(localDateTime).plusDays(1).minusNanos(1);
    }
}
